<script>
      class PromisePool {
            constructor(max, fn, callback) {
                this.max = max; //最大并发量
                this.fn = fn; //自定义的请求函数
                this.pool = []; //并发池
                this.list = []; //剩余的请求地址
                this.callback = callback;//所有请求执行完的回调
            }
            start(list) {
                this.list = list; //先循环把并发池塞满
                while (this.pool.length < this.max && this.list.length) {
                    let item = this.list.shift();
                    this.setTask(item);
                }
                //利用Promise.all方法来获得并发池中某任务完成的信号
                let race = Promise.race(this.pool);
                this.run(race);
            }
            run(race) {
                race
                    .then(res => {
                        //每当并发池跑完一个任务，就再塞入一个任务
                        let item = this.list.shift();
                        this.setTask(item);
                        this.run(Promise.race(this.pool));
                    })
            }
            setTask(item) {
                if (!item) return
                let task = this.fn(item);
                this.pool.push(task); //将该任务推入pool并发池中
                // console.log(`\x1B[43m ${item} 开始，当前并发数：${this.pool.length}`)
                task.then(res => {
                    //请求结束后将该Promise任务从并发池中移除
                    this.pool.splice(this.pool.indexOf(task), 1);
                    this.callback(this.list.length)
                    // console.log(`\x1B[43m ${item} 结束，当前并发数：${this.pool.length}`);
                })
            }
        }
        //requestFn表示自定义每次任务执行完成的回调
        const requestFn = elem => {
            return new Promise((resolve) => {
                // 单个任务执行完成的回调，这里可以处理对应的业务逻辑,发送ajax请求
                resolve()
            })
        }
        const pool = new PromisePool(5, requestFn, (num) => {  //5表示并发的数量
            if (num === 0) {
                //所有任务执行完毕
                console.log('所有任务执行完毕');
            }
        });
        console.log(pool);
        pool.start(['地址1', '地址2', '地址3', '地址4', '地址5', '地址6', '地址7', '地址8', '地址9', '地址10']);
</script>
